define(["require", "exports", "vscode-languageserver-protocol", "vscode-languageclient/utils/is"], function (require, exports, proto, Is) {
    /* --------------------------------------------------------------------------------------------
     * Copyright (c) Microsoft Corporation. All rights reserved.
     * Licensed under the MIT License. See License.txt in the project root for license information.
     * ------------------------------------------------------------------------------------------ */
    'use strict';
    Object.defineProperty(exports, "__esModule", { value: true });
    var vscode;
    function createConverter(vscode_1, uriConverter) {
        vscode = vscode_1;
        const nullConverter = (value) => value.toString();
        const _uriConverter = uriConverter || nullConverter;
        function asUri(value) {
            return _uriConverter(value);
        }
        function asTextDocumentIdentifier(textDocument) {
            return {
                uri: _uriConverter(textDocument.uri)
            };
        }
        function asVersionedTextDocumentIdentifier(textDocument) {
            return {
                uri: _uriConverter(textDocument.uri),
                version: textDocument.version
            };
        }
        function asOpenTextDocumentParams(textDocument) {
            return {
                textDocument: {
                    uri: _uriConverter(textDocument.uri),
                    languageId: textDocument.languageId,
                    version: textDocument.version,
                    text: textDocument.getText()
                }
            };
        }
        function isTextDocumentChangeEvent(value) {
            let candidate = value;
            return !!candidate.document && !!candidate.contentChanges;
        }
        function isTextDocument(value) {
            let candidate = value;
            return !!candidate.uri && !!candidate.version;
        }
        function asChangeTextDocumentParams(arg) {
            if (isTextDocument(arg)) {
                let result = {
                    textDocument: {
                        uri: _uriConverter(arg.uri),
                        version: arg.version
                    },
                    contentChanges: [{ text: arg.getText() }]
                };
                return result;
            }
            else if (isTextDocumentChangeEvent(arg)) {
                let document = arg.document;
                let result = {
                    textDocument: {
                        uri: _uriConverter(document.uri),
                        version: document.version
                    },
                    contentChanges: arg.contentChanges.map((change) => {
                        let range = change.range;
                        return {
                            range: {
                                start: { line: range.start.line, character: range.start.character },
                                end: { line: range.end.line, character: range.end.character }
                            },
                            rangeLength: change.rangeLength,
                            text: change.text
                        };
                    })
                };
                return result;
            }
            else {
                throw Error('Unsupported text document change parameter');
            }
        }
        function asCloseTextDocumentParams(textDocument) {
            return {
                textDocument: asTextDocumentIdentifier(textDocument)
            };
        }
        function asSaveTextDocumentParams(textDocument, includeContent = false) {
            let result = {
                textDocument: asVersionedTextDocumentIdentifier(textDocument)
            };
            if (includeContent) {
                result.text = textDocument.getText();
            }
            return result;
        }
        function asTextDocumentSaveReason(reason) {
            switch (reason) {
                case vscode.TextDocumentSaveReason.Manual:
                    return proto.TextDocumentSaveReason.Manual;
                case vscode.TextDocumentSaveReason.AfterDelay:
                    return proto.TextDocumentSaveReason.AfterDelay;
                case vscode.TextDocumentSaveReason.FocusOut:
                    return proto.TextDocumentSaveReason.FocusOut;
            }
            return proto.TextDocumentSaveReason.Manual;
        }
        function asWillSaveTextDocumentParams(event) {
            return {
                textDocument: asTextDocumentIdentifier(event.document),
                reason: asTextDocumentSaveReason(event.reason)
            };
        }
        function asTextDocumentPositionParams(textDocument, position) {
            return {
                textDocument: asTextDocumentIdentifier(textDocument),
                position: asWorkerPosition(position)
            };
        }
        function asTriggerKind(triggerKind) {
            switch (triggerKind) {
                case vscode.CompletionTriggerKind.TriggerCharacter:
                    return proto.CompletionTriggerKind.TriggerCharacter;
                case vscode.CompletionTriggerKind.TriggerForIncompleteCompletions:
                    return proto.CompletionTriggerKind.TriggerForIncompleteCompletions;
                default:
                    return proto.CompletionTriggerKind.Invoked;
            }
        }
        function asCompletionParams(textDocument, position, context) {
            return {
                textDocument: asTextDocumentIdentifier(textDocument),
                position: asWorkerPosition(position),
                context: {
                    triggerKind: asTriggerKind(context.triggerKind),
                    triggerCharacter: context.triggerCharacter
                }
            };
        }
        function asWorkerPosition(position) {
            return { line: position.line, character: position.character };
        }
        function asPosition(value) {
            if (value === void 0) {
                return undefined;
            }
            else if (value === null) {
                return null;
            }
            return { line: value.line, character: value.character };
        }
        function asRange(value) {
            if (value === void 0 || value === null) {
                return value;
            }
            return { start: asPosition(value.start), end: asPosition(value.end) };
        }
        function asDiagnosticSeverity(value) {
            switch (value) {
                case vscode.DiagnosticSeverity.Error:
                    return proto.DiagnosticSeverity.Error;
                case vscode.DiagnosticSeverity.Warning:
                    return proto.DiagnosticSeverity.Warning;
                case vscode.DiagnosticSeverity.Information:
                    return proto.DiagnosticSeverity.Information;
                case vscode.DiagnosticSeverity.Hint:
                    return proto.DiagnosticSeverity.Hint;
            }
            return proto.DiagnosticSeverity.Error;
        }
        function asDiagnostic(item) {
            let result = proto.Diagnostic.create(asRange(item.range), item.message);
            if (Is.number(item.severity)) {
                result.severity = asDiagnosticSeverity(item.severity);
            }
            if (Is.number(item.code) || Is.string(item.code)) {
                result.code = item.code;
            }
            if (item.source) {
                result.source = item.source;
            }
            return result;
        }
        function asDiagnostics(items) {
            if (items === void 0 || items === null) {
                return items;
            }
            return items.map(asDiagnostic);
        }
        function asDocumentation(format, documentation) {
            switch (format) {
                case '$string':
                    return documentation;
                case proto.MarkupKind.PlainText:
                    return { kind: format, value: documentation };
                case proto.MarkupKind.Markdown:
                    return { kind: format, value: documentation.value };
                default:
                    return `Unsupported Markup content received. Kind is: ${format}`;
            }
        }
        function asCompletionItemKind(value, original) {
            if (original !== void 0) {
                return original;
            }
            return value + 1;
        }
        function asCompletionItem(item) {
            let result = { label: item.label };
            let protocolItem = item;
            if (item.detail) {
                result.detail = item.detail;
            }
            // We only send items back we created. So this can't be something else than
            // a string right now.
            if (item.documentation) {
                if (!protocolItem || protocolItem.documentationFormat === '$string') {
                    result.documentation = item.documentation;
                }
                else {
                    result.documentation = asDocumentation(protocolItem.documentationFormat, item.documentation);
                }
            }
            if (item.filterText) {
                result.filterText = item.filterText;
            }
            fillPrimaryInsertText(result, item);
            if (Is.number(item.kind)) {
                result.kind = asCompletionItemKind(item.kind, protocolItem && protocolItem.originalItemKind);
            }
            if (item.sortText) {
                result.sortText = item.sortText;
            }
            if (item.additionalTextEdits) {
                result.additionalTextEdits = asTextEdits(item.additionalTextEdits);
            }
            if (item.commitCharacters) {
                result.commitCharacters = item.commitCharacters.slice();
            }
            if (item.command) {
                result.command = asCommand(item.command);
            }
            if (protocolItem && protocolItem.data) {
                result.data = protocolItem.data;
            }
            return result;
        }
        function fillPrimaryInsertText(target, source) {
            let format = proto.InsertTextFormat.PlainText;
            let text;
            let range = undefined;
            if (source.textEdit) {
                text = source.textEdit.newText;
                range = asRange(source.textEdit.range);
            }
            else if (proto.InsertTextFormat && proto.InsertTextFormat.Snippet) {
                format = proto.InsertTextFormat.Snippet;
                text = source.insertText.value;
            }
            else {
                text = source.insertText;
            }
            if (source.range) {
                range = asRange(source.range);
            }
            target.insertTextFormat = format;
            if (source.fromEdit && text && range) {
                target.textEdit = { newText: text, range: range };
            }
            else {
                target.insertText = text;
            }
        }
        function asTextEdit(edit) {
            return { range: asRange(edit.range), newText: edit.newText };
        }
        function asTextEdits(edits) {
            if (edits === void 0 || edits === null) {
                return edits;
            }
            return edits.map(asTextEdit);
        }
        function asReferenceParams(textDocument, position, options) {
            return {
                textDocument: asTextDocumentIdentifier(textDocument),
                position: asWorkerPosition(position),
                context: { includeDeclaration: options.includeDeclaration }
            };
        }
        function asCodeActionContext(context) {
            if (context === void 0 || context === null) {
                return context;
            }
            return proto.CodeActionContext.create(asDiagnostics(context.diagnostics));
        }
        function asCommand(item) {
            let result = proto.Command.create(item.title, item.command);
            if (item.arguments) {
                result.arguments = item.arguments;
            }
            return result;
        }
        function asCodeLens(item) {
            let result = proto.CodeLens.create(asRange(item.range));
            if (item.command) {
                result.command = asCommand(item.command);
            }
            if (item.data) {
                result.data = item.data;
            }
            ;
            return result;
        }
        function asFormattingOptions(item) {
            return { tabSize: item.tabSize, insertSpaces: item.insertSpaces };
        }
        function asDocumentSymbolParams(textDocument) {
            return {
                textDocument: asTextDocumentIdentifier(textDocument)
            };
        }
        function asCodeLensParams(textDocument) {
            return {
                textDocument: asTextDocumentIdentifier(textDocument)
            };
        }
        function asDocumentLink(item) {
            let result = proto.DocumentLink.create(asRange(item.range));
            if (item.target) {
                result.target = asUri(item.target);
            }
            return result;
        }
        function asDocumentLinkParams(textDocument) {
            return {
                textDocument: asTextDocumentIdentifier(textDocument)
            };
        }
        return {
            asUri,
            asTextDocumentIdentifier,
            asOpenTextDocumentParams,
            asChangeTextDocumentParams,
            asCloseTextDocumentParams,
            asSaveTextDocumentParams,
            asWillSaveTextDocumentParams,
            asTextDocumentPositionParams,
            asCompletionParams,
            asWorkerPosition,
            asRange,
            asPosition,
            asDiagnosticSeverity,
            asDiagnostic,
            asDiagnostics,
            asCompletionItem,
            asTextEdit,
            asReferenceParams,
            asCodeActionContext,
            asCommand,
            asCodeLens,
            asFormattingOptions,
            asDocumentSymbolParams,
            asCodeLensParams,
            asDocumentLink,
            asDocumentLinkParams
        };
    }
    exports.createConverter = createConverter;
});
